package com.cloudfun.msglisten.controller;

import com.cloudfun.campusshare.RemoteAppService;
import com.cloudfun.campusshare.dto.AppDTO;
import com.cloudfun.msglisten.common.constant.ExternalRabbitConstants;
import com.cloudfun.msglisten.common.model.dto.RabbitResCheckDTO;
import com.cloudfun.msglisten.common.model.dto.RabbitTopicCheckDTO;
import com.cloudfun.msglisten.common.model.dto.RabbitVirtualHostCheckDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by Huqin on 2020/3/30
 */
@Order(Integer.MIN_VALUE)
@Slf4j
@RestController
@RequestMapping(path = "/rabbit/auth", method = {RequestMethod.GET, RequestMethod.POST})
public class RabbitMQAuthEndpoint {

    private final String ALLOW = "allow";
    private final String DENY = "deny";

    private static final String EXTERNAL_VIRTUAL_HOST = "external";

    @Reference(timeout = 3_000)
    private RemoteAppService remoteAppService;

    @RequestMapping("/user")
    public String user(@RequestParam("username") String appKey,
                       @RequestParam("password") String secretKey) {
        log.info("Trying to authenticate user {}", appKey);
        AppDTO appDTO = remoteAppService.getByAppKey(appKey);
        if (null == appDTO) {
            log.error("Deny authenticate user {}", appKey);
            return DENY;
        }
        if (appDTO.getSecretKey().equals(secretKey)) {
            return ALLOW;
        } else {
            log.error("Deny authenticate user {}", appKey);
            return DENY;
        }
    }

    @RequestMapping("/vhost")
    public String vhost(RabbitVirtualHostCheckDTO checkDTO) {
        log.info("Checking vhost access with {}", checkDTO);
        // vhost只开放external
        if (checkDTO.getVhost().equals(EXTERNAL_VIRTUAL_HOST)) {
            return ALLOW;
        }
        log.error("Deny vhost access with {}", checkDTO);
        return DENY;
    }

    @RequestMapping("/resource")
    public String resource(RabbitResCheckDTO checkDTO) {
        log.info("Checking resource access with {}", checkDTO);
        AppDTO appDTO = remoteAppService.getByAppKey(checkDTO.getUsername());
        if (null == appDTO) {
            log.error("Deny authenticate user {}", checkDTO.getUsername());
            return DENY;
        }
        Set<String> allowQueueSet = ExternalRabbitConstants.Queue.SUFFIX_LIST.stream()
                .map(suffix -> appDTO.getAppId() + "." + suffix)
                .collect(Collectors.toSet());
        // resource对外只开放queue的read权限
        if (checkDTO.getVhost().equals(EXTERNAL_VIRTUAL_HOST) && checkDTO.getResource().equals("queue")
                && allowQueueSet.contains(checkDTO.getName()) && checkDTO.getPermission().equals("read")) {
            return ALLOW;
        }
        log.error("Deny resource access with {}", checkDTO);
        return DENY;
    }

    @RequestMapping("/topic")
    public String topic(RabbitTopicCheckDTO checkDTO) {
        log.info("Checking topic access with {}", checkDTO);
        // topic对外不开放
        log.error("Deny topic access with {}", checkDTO);
        return DENY;
    }

}
